<?php
class backupclass {

	function backupclass() {
		global $setupdata, $mysqlclass;
		$this->setupdata=$setupdata;
		$this->mysqlclass=$mysqlclass;

		$is_safe_mode = ini_get('safe_mode') == '1' ? 1 : 0;
		if (!$is_safe_mode) set_time_limit(0);
	}
	
	function get_filelist($dir){ 
		$filelist = array(); 
		$dh = opendir($dir); 
		if ($dh === NULL) return $filelist; 
		else $filelist[] = $dir; 
		while (($file = readdir($dh)) !== false) { 
			if ($file == '.' || $file == '..') continue; 
			if (strpos($file, 'Thumbs.db')) continue; 
			$filelist[] = $dir.'/'.$file; 
			$filename = $dir.'/'.$file; 
			if (is_dir($filename)) { 
				$tmp = $this->get_filelist($filename); 
				$n = sizeof($tmp); 
				for ($i = 0; $i < $n; $i++) $filelist[] = $tmp[$i]; 
			} 
		} 
		closedir($dh);
		return $filelist; 
	}
	
	function copy_file_fp($src_fp, $dst_fp, $file_size, $buffer_size = 0x10000){ 
		while (!feof($src_fp) && $file_size) { 
			if ($buffer_size > $file_size) $buffer_size = $file_size; 
			$file_size -= fwrite($dst_fp, fread($src_fp, $buffer_size)); 
		} 
	} 
	
	function delete_dir($dir){
		if (is_dir($dir)){
			$items = $this->get_filelist($dir);
			rsort($items);
			foreach ($items as $item) {
				if (is_dir($item)) @rmdir($item);
				if (is_file($item)) @unlink($item);
			}
		}
	}

	function delete_file($file){
		if (strlen($file)>6){
			$file = $this->setupdata['modules']['backup']['path']."/".$file;
			if (is_file($file)) unlink($file);
		}
	}

	function upload_file($file){
		if (($file['error'] == 0) && ($file['size']) > 100){
			if (isset($this->setupdata['modules']['backup']['path']) && is_dir($this->setupdata['modules']['backup']['path'])){
				$file['name'] = "/backup_".date('Ymd_His').".gz";
				$res = copy($file['tmp_name'], $this->setupdata['modules']['backup']['path']."/".$file['name']);
				if ($res) return 0;
			}
		}
		return 33;
	}
	
	function download_file($file_name){
		if (strlen($file_name)>6){
			$file = $this->setupdata['modules']['backup']['path']."/".$file_name;
			if (is_file($file)) {
				header("Pragma: public");
				header("Expires: 0");
				header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
				header("Cache-Control: private", false);
				header('Content-type: application/x-gzip-compressed');
				header('Content-Disposition: attachment; filename="'.$file_name.'"');
				header("Content-Transfer-Encoding: binary");
				header('Content-length: '.filesize($file));
				$handle = fopen($file, 'rb');
				while (!feof($handle)){
					$buffer = fread($handle, 1048576);
					echo $buffer;
				}
				fclose($handle);
				exit;
			}
		}
	}
	
	function get_backups(){
		$result = array();
		$array = $this->get_filelist($this->setupdata['modules']['backup']['path']);
		foreach ($array as $item) {
			if (strpos($item, ".gz") !== false) $t = explode("/", $item);
			else $t = array();
			if (strlen($t[count($t)-1]) > 0) {
				$date = explode("_", $t[count($t)-1]);
				$time = explode(".", $date[2]);
				$date = $date[1];
				$time = $time[0];
				$result[$t[count($t)-1]]['date'] = mktime(substr($time, 0, 2), substr($time, 2, 2), substr($time, 4, 2), substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4));
				$result[$t[count($t)-1]]['size'] = round(filesize($item)/1024, 2);
			}
		}
		return $result;
	}
	
	function restore_backup($file_name){
		if (strlen($file_name)>6){
			$file = $this->setupdata['modules']['backup']['path']."/".$file_name;
			if (is_file($file)) {
				$this->delete_dir("client");
				$this->delete_dir($this->setupdata['binary_path']);
				$this->delete_dir($this->setupdata['smarty_guest_template_dir']."guest");
				$this->unarchive_dir($file, "");
				$this->import_mysql($this->setupdata['smarty_compile_dir']."mysql");
				$this->delete_dir($this->setupdata['smarty_compile_dir'].$this->setupdata['smarty_compile_dir']."mysql");
			}
		}
	}
	
	function create_backup($output='server'){
		$dirs[] = $this->setupdata['binary_path'];
		$dirs[] = "client";
		$dirs[] = $this->setupdata['smarty_guest_template_dir']."guest";
		$this->dump_mysql($this->setupdata['smarty_compile_dir']."mysql");
		$dirs[] = $this->setupdata['smarty_compile_dir']."mysql";
		if ($output == "server") $this->archive_dir($this->setupdata['modules']['backup']['path'], $dirs);
		elseif ($output == "file") $this->archive_dir_to_download($dirs);
		$this->delete_dir($this->setupdata['smarty_compile_dir']."mysql");
	}
	
	function archive_dir_to_download($src_dirs){
		$tmpfname = tempnam("/tmp", "mysql_");
		$archive_file = $tmpfname;
		$error = 0;
		if (is_file($archive_file)) unlink($archive_file); 
		$dst_fp = @fopen("compress.zlib://{$archive_file}", 'wb'); 
		if ($dst_fp === false) $dst_fp = @fopen($archive_file, 'wb'); 
		if ($dst_fp === false) return 32;
		foreach ($src_dirs as $src_dir){
			if (!is_dir($src_dir)) return 30;
			$files = $this->get_filelist($src_dir); 
			$n = sizeof($files); 
			for ($i = 0; $i < $n; $i++) { 
				$file = $files[$i]; 
				$filename = $file; 
				if (is_dir($filename)) { 
					fwrite($dst_fp, "d{$file}\n"); 
				} else { 
					$src_fp = fopen($filename, 'rb'); 
					if ($src_fp === NULL) { 
						$error = 33;
						continue; 
					} 
					$stat = stat($filename); 
					$size = $stat['size']; 
					$mode = $stat['mode'] & 0777; 
					$tmp = pack('Vv', $size, $mode); 
					fwrite($dst_fp, "f{$file}\n{$tmp}"); 
					$this->copy_file_fp($src_fp, $dst_fp, $size); 
					fclose($src_fp); 
				} 
			} 
		}
		fclose($dst_fp); 
		header("Pragma: public");
		header("Expires: 0");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Cache-Control: private", false);
		header('Content-type: application/x-gzip-compressed');
		header('Content-Disposition: attachment; filename="backup_'.date('Ymd_His').'.gz"');
		header("Content-Transfer-Encoding: binary");
		header('Content-length: '.filesize($archive_file));
		$handle = fopen($file, 'rb');
		while (!feof($handle)){
			$buffer = fread($handle, 1048576);
			echo $buffer;
		}
		fclose($handle);
		unlink($archive_file);
		exit;
		return $error;
	}
	
	function archive_dir($archive_dir, $src_dirs){ 
		$dirs = explode("/", $archive_dir);
		$i = 0; $dir = $dirs[0];
		while ($i < count($dirs)) {
			if (!is_dir($dir)) mkdir($dir, 0777); 
			$i++;
			if (isset($dirs[$i])) $dir .= '/'.$dirs[$i];
		}
		if (!is_dir($archive_dir)) return 32;
		$archive_file = $archive_dir."/backup_".date('Ymd_His').".gz";
		$error = 0;
		if (is_file($archive_file)) unlink($archive_file); 
		$dst_fp = @fopen("compress.zlib://{$archive_file}", 'wb'); 
		if ($dst_fp === false) $dst_fp = @fopen($archive_file, 'wb'); 
		if ($dst_fp === false) return 32;
		foreach ($src_dirs as $src_dir){
			if (!is_dir($src_dir)) return 30;
			$files = $this->get_filelist($src_dir); 
			$n = sizeof($files); 
			for ($i = 0; $i < $n; $i++) { 
				$file = $files[$i]; 
				$filename = $file; 
				if (is_dir($filename)) { 
					fwrite($dst_fp, "d{$file}\n"); 
				} else { 
					$src_fp = fopen($filename, 'rb'); 
					if ($src_fp === NULL) { 
						$error = 33;
						continue; 
					} 
					$stat = stat($filename); 
					$size = $stat['size']; 
					$mode = $stat['mode'] & 0777; 
					$tmp = pack('Vv', $size, $mode); 
					fwrite($dst_fp, "f{$file}\n{$tmp}"); 
					$this->copy_file_fp($src_fp, $dst_fp, $size); 
					fclose($src_fp); 
				} 
			} 
		}
		fclose($dst_fp); 
		return $error;
	} 
	
	function unarchive_dir($archive_file, $dst_dir){ 
		$error = 0;
		if (!is_file($archive_file)) return 31;
//		if (!is_dir($dst_dir)) return 30;
		$not_eof = 1; 
		$src_fp = @fopen("compress.zlib://{$archive_file}", 'rb'); 
		if ($src_fp === false) $src_fp = @fopen($archive_file, 'rb'); 
		if ($src_fp === false) return 31;
		while ($not_eof) { 
			switch (fgetc($src_fp)) { 
				case 'f' :
					$file = substr(fgets($src_fp, 0x10000), 0, -1); 
					$tmp = unpack('Vsize/vmode', fread($src_fp, 6)); 
					$size = $tmp['size']; 
					$mode = $tmp['mode']; 
					$filename = $dst_dir.$file; 
					$dst_fp = fopen($filename, 'wb'); 
					if ($dst_fp === NULL) $error = 34;
					else $this->copy_file_fp($src_fp, $dst_fp, $size); 
					fclose($dst_fp); 
					chmod($filename, $mode); 
					break; 
				case 'd' :
					$file = substr(fgets($src_fp, 0x10000), 0, -1); 
					$dirname = $dst_dir.$file; 
					if (!is_dir($dirname)) {
						$dirs = explode("/", $dirname);
						$i = 0; $dir = $dirs[0];
						while ($i < count($dirs)) {
							if (!is_dir($dir)) mkdir($dir, 0777); 
							$i++;
							if (isset($dirs[$i])) $dir .= '/'.$dirs[$i];
						}
					}
					break; 
				case false : 
					$not_eof = 0; 
					break; 
				default :
					$error = 35; 
					break; 
			} 
		} 
    	fclose($src_fp); 
		return $error;
	} 
	
	function dump_mysql($dir){
		/*
		$host = strpos($this->setupdata['HostName'], 'localhost');
		if ($host === false) $host = 0; // not localhost server
		elseif ($host == 0) $host = 1; // localhost
		else $host = 0; // not localhost server
		*/
		$host = 0;
		
		$cur_dir = $dir;
		$dirs = explode("/", $dir);
		$i = 0; $dir = $dirs[0];
		while ($i < count($dirs)) {
			if (!is_dir($dir)) mkdir($dir, 0777); 
			$i++;
			if (isset($dirs[$i])) $dir .= '/'.$dirs[$i];
		}
		$result = $this->mysqlclass->mysql_my_query("SHOW TABLES", __LINE__, __FILE__);
		$archive_file = $cur_dir."/main.sql";
		$fp_main = fopen("compress.zlib://{$archive_file}", 'wb');
		if ($fp_main === false) $fp_main = fopen($archive_file, 'wb'); 
		if ($fp_main === false) return 31;
		while($row = mysql_fetch_array($result)) {
			if ((strpos($row[0], $this->setupdata['table_prefix']) !== false) && ($row[0] != $this->setupdata['table_prefix']."discribe") && (!preg_match("/".join($this->setupdata['vars']['tables_not_update'],'|')."/", $row[0]))) {
				$archive_file = $cur_dir.'/'.$row[0].".sql";
				$fp = fopen("compress.zlib://{$archive_file}", 'wb');
				if ($fp === false) $fp = fopen($archive_file, 'wb'); 
				if ($fp_main === false) return 31;
				$sql1 = $this->mysqlclass->mysql_my_query("SHOW CREATE TABLE `".$row[0]."`", __LINE__, __FILE__);
				$tab = mysql_fetch_array($sql1);
				$content = "DROP TABLE IF EXISTS `".$row[0]."`;\n";
				$content .= $tab[1].";\n";
				fwrite($fp_main, $content);
				$fields = array();
				$sql2 = mysql_query("SHOW COLUMNS FROM `".$row[0]."`");
				while($col = mysql_fetch_row($sql2)) $fields[$col[0]] = preg_match("/^(\w*int|year)/", $col[1]) ? 1 : 0;
				$from = 0; $limit = 250;
				while(($sql3 = $this->mysqlclass->mysql_my_query("SELECT * FROM `".$row[0]."` LIMIT ".$from.", ".$limit, __LINE__, __FILE__)) && ($total = mysql_num_rows($sql3))){
					while($row3 = mysql_fetch_array($sql3, MYSQL_ASSOC)) {
						$content = "INSERT INTO `".$row[0]."` ";
						$tmp1 = $tmp2 = array();
						foreach ($row3 as $key=>$value){
							if ($fields[$key]) $tmp2[$key] = isset($row3[$key]) ? $row3[$key] : "NULL";
							else {
								$row3[$key] = addslashes($row3[$key]);
								$row3[$key] = str_replace("\r", "\\r", $row3[$key]);
								$row3[$key] = str_replace("\n", "\\n", $row3[$key]);
								$tmp2[$key] = isset($row3[$key]) ? "'".$row3[$key]."'" : "NULL";
							}
							$tmp1[$key] = "`".$key."`";
						}
						$content .=  "(".implode(",", $tmp1).") VALUES (".implode(",", $tmp2).");\n";
						//$content .=  " VALUES (".implode(",", $tmp2).");\n";
						fwrite($fp, $content);
					}
					mysql_free_result($sql3);
					if ($total < $limit) break;
					$from += $limit;
				}
				mysql_free_result($sql1);
				mysql_free_result($sql2);
				fclose($fp);
			}
		}
		fclose($fp_main);
	}
	
	function import_mysql($dir){
		/*
		$host = strpos($this->setupdata['HostName'], 'localhost');
		if ($host === false) $host = 0; // not localhost server
		elseif ($host == 0) $host = 1; // localhost
		else $host = 0; // not localhost server
		*/
		$host = 0;
		
		if (!is_file($dir."/main.sql")) return 31;
		$file = $dir."/main.sql";
		$src_fp = @fopen("compress.zlib://{$file}", 'rb'); 
		if ($src_fp === false) $src_fp = @fopen($file, 'rb'); 
		if ($src_fp === false) return 31;
		$contents = '';
		while (!feof($src_fp)) $contents .= fread($src_fp, 8192);
		fclose($src_fp);
		$t = explode(";\n", $contents);
		foreach ($t as $data) {
			if (strlen($data) > 0) $this->mysqlclass->mysql_my_query($data, __LINE__, __FILE__);
		}
		$files = $this->get_filelist($dir); 
		foreach ($files as $file){
			if (is_file($file) && (strpos($file, 'main.sql') === false)){
				$src_fp = @fopen("compress.zlib://{$file}", 'rb'); 
				if ($src_fp === false) $src_fp = @fopen($file, 'rb'); 
				if ($src_fp === false) return 31;
				$contents = '';
				while (!feof($src_fp)) $contents .= fread($src_fp, 8192);
				$tmpfname = tempnam("/tmp", "mysql_");
				$handle = fopen($tmpfname, "wb");
				fwrite($handle, $contents);
				fclose($handle);
				$t = explode("/", $file);
				$t = explode(".", $t[count($t)-1]);
				$tmpfname = addslashes($tmpfname);
				if ($host == 1) {
					$this->mysqlclass->mysql_my_query("LOAD DATA INFILE '".$tmpfname."' INTO TABLE `".$t[count($t)-2]."` FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\n'", __LINE__, __FILE__);
				} else {
					$array = file($tmpfname);
					foreach ($array as $value){
						$value = substr($value, 0, -1);
						$this->mysqlclass->mysql_my_query($value, __LINE__, __FILE__);
					}
				}
				unlink($tmpfname);
				fclose($src_fp);
			}
		}
	}
}
?>
